#include <iostream>
#include <string>
#include <cstring>
#include <thread>
#include <pthread.h>
#include <unistd.h>



// void *start(void *args)
// {
//     //std::string name = static_cast<char *>(args);
//     while (true)
//     {
//         std::cout << "I am a new thread" << std::endl;
//         sleep(1);
//         //break;
//     }

//     //pthread_exit((void *)10);
// }

// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, start, (void *)"thread-1");

//     sleep(5);

//     pthread_cancel(tid);
//     std::cout << "取消线程: " << tid << std::endl;

//     sleep(5);

//     void *ret = nullptr;
//     pthread_join(tid, &ret);
//     std::cout << "new thread exit code: " << (long long int)ret << std::endl;

//     return 0;
// }

// class ThreadData
// {
// public:
//     ThreadData() {}

//     ~ThreadData() {}

//     void Init(const std::string name, int a, int b)
//     {
//         _name = name;
//         _a = a;
//         _b = b;
//     }

//     void Excute() { _result = _a + _b; }
//     int Result() { return _result; }
//     std::string Name() { return _name; }
//     void SetTid(pthread_t tid) { _tid = tid; }
//     pthread_t GetTid() { return _tid; }
//     int GetA() { return _a; }
//     int GetB() { return _b; }

// private:
//     std::string _name;
//     int _a;
//     int _b;
//     int _result;
//     pthread_t _tid;
// };

// void *routine(void *args)
// {
//     ThreadData *td = static_cast<ThreadData *>(args);
//     while (true)
//     {
//         std::cout << "我是新线程, 我的名字是: " << td->Name() << ", my tid is: " << pthread_self() << std::endl;
//         // std::cout << "task result is: " << td->Excute() << std::endl;
//         td->Excute();
//         sleep(1);
//         break;
//     }

//     // 线程返回值参数可以是: 变量, 数值, 对象

//     // 线程退出方式
//     // 1.线程入口函数 return, 表示线程退出
//     return (void *)td;
// }

// #define NUM 10

// int main()
// {
//     ThreadData td[NUM];

//     // 1.初始化数据
//     for (int i = 0; i < NUM; i++)
//     {
//         char buffer[64];
//         snprintf(buffer, sizeof(buffer), "thread-%d", i);
//         td[i].Init(buffer, i * 10, i * 20);
//     }

//     // 2.创建多个线程
//     for (int i = 0; i < NUM; i++)
//     {
//         pthread_t tid;
//         pthread_create(&tid, nullptr, routine, (void *)&td[i]);
//         td[i].SetTid(tid);
//     }

//     // 3.等待多个线程
//     for (int i = 0; i < NUM; i++)
//     {
//         ThreadData *rtd = nullptr;
//         pthread_join(td[i].GetTid(), (void **)&rtd); 
//         // 本质: rtd等价于routine函数的返回值(rtd = &td[i])
//     }

//     // 4.获取结果
//     for (int i = 0; i < NUM; i++)
//     {
//         printf("td[%d]: %d + %d = %d, tid = %ld\n", i, td[i].GetA(), td[i].GetB(), td[i].Result(), td[i].GetTid());
//     }

//     return 0;
// }

// int main()
// {
//     ThreadData *td = new ThreadData("thread-1", 10, 20);

//     pthread_t tid;
//     // 线程创建传递参数可以是: 变量, 数值, 对象
//     pthread_create(&tid, nullptr, routine, (void *)td);

//     ThreadData *rtd = nullptr;
//     // 线程等待: 第二个参数指向线程的返回值
//     int n = pthread_join(tid, (void **)&rtd); // 保证执行完毕, 任务一定处理完了, 结果变量一定写入了
//     if (n != 0)
//     {
//         std::cout << "join error: " << n << ", " << strerror(n) << std::endl;
//         return 1;
//     }
//     std::cout << "join success, ret: " << rtd->Result() << std::endl;

//     delete td;

//     return 0;
// }

// 5. 全局变量在线程内部是共享的
int gval = 100;

std::string toHex(pthread_t tid)
{
    // 4. 进程内的函数，线程共享
    char buffer[64];
    snprintf(buffer, sizeof(buffer), "0x%lx", tid);
    return buffer;
}

// 不可重入函数：被多个执行流执行
void *routine1(void *args)
{
    std::string name = static_cast<const char *>(args);
    while (true)
    {
        // 3. 不加保护的情况下，显示器文件就是共享资源，打印到显示器中的数据是乱序的
        std::cout << name << " tid: " << toHex(pthread_self()) << "全局变量(修改): " << gval << std::endl;
        gval++;
        sleep(1);

        // 6. 线程一但出现异常，可能会导致其它线程全面崩溃
        // 6.1 任何一个线程都是进程的一个执行分支，线程出错，等同进程出错
        // 6.2 线程出现野指针，就是页表查失败了，MMU报错，CPU内部触发软中断，
        //     根据中断号，查中断向量表，进行异常处理，给目标进程发信号，
        //     信号的处理方式每一个线程是共享的，所以每个线程都退出了。
        int *p = nullptr;
        *p = 10;
    }
}

void *routine2(void *args)
{
    std::string name = static_cast<const char *>(args);
    while (true)
    {
        std::cout << name << " tid: " << toHex(pthread_self()) << ", 全局变量(检测): " << gval << std::endl;
        sleep(1);
    }
}

// int main()
// {
//     // 1. 新线程和主线程谁先运行，不确定；父进程和子进程谁先运行，不确定
//     // 2. 线程创建出来，要对进程的时间片进行瓜分

//     pthread_t tid1;
//     pthread_create(&tid1, nullptr, routine1, (void *)"thread-1");

//     pthread_t tid2;
//     pthread_create(&tid2, nullptr, routine2, (void *)"thread-2");

//     // 7. 线程创建之后，也是要被等待和回收的
//     // 7.1 理由: a. 类似僵尸进程的问题 b. 为了知道线程的执行结果

//     while (true)
//     {
//         std::cout << "main thread pid: " << toHex(pthread_self()) << std::endl;
//         sleep(1);
//     }

//     return 0;
// }

// int main()
// {
//     std::string name = "thread-1";
//     std::thread t([&](){
//         while(true)
//         {
//             std::cout << "new thread, name: " << name << ", pid: " << getpid() << std::endl;
//             sleep(1);
//         }
//     });

//     while(true)
//     {
//         std::cout << "main thread, pid: " << getpid() << std::endl;
//         sleep(1);
//     }
// }